//
//  OCLinkInfo.m
//  RoutingEvaluator
//
//  Created by Christopher Kemsley on 4/15/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#import "OCLinkInfo.h"

using namespace Sim ;


@implementation OCLinkInfo {
	LinkInfo	*	info ;
	NSSet		*	endpoints ;
}
@synthesize info , endpoints ;
@dynamic distance , cost ;


- (id)	initWithLinkInfo:(Sim::LinkInfo*)i {
	if ( (self = [super init]) )
		{
		info = i ;
		endpoints = [NSSet setWithObjects:
					 [ [OCNodeInfo alloc] initWithNodeInfo:info->endpoint1 ] ,
					 [ [OCNodeInfo alloc] initWithNodeInfo:info->endpoint2 ] ,
					 nil] ;
		}
	return self ;
}


- (Float64)	distance {
	return info -> distance() ;
}
- (Float64)	cost {
	return info -> cost() ;
}


- (OCNodeInfo*)	oppositeEndpointFrom:(OCNodeInfo*)node {
	NSEnumerator	*	here	=	[endpoints objectEnumerator] ;
	
	OCNodeInfo		*	node1	=	[here nextObject] ;
	OCNodeInfo		*	node2	=	[here nextObject] ;
	
	if ( [node1 isEqual:node] )
		return node2 ;
	
	if ( [node2 isEqual:node] )
		return node1 ;
	
	return 0 ;
}


- (NSUInteger) hash {
	return (NSUInteger)info ;
}
- (BOOL)	isEqual:(id)object {
	if ( [object isKindOfClass:[OCLinkInfo class]] )
		{
		OCLinkInfo * link = object ;
		return info == [link info] ;
		}
	return false ;
}
- (NSString*)	description {
	return [ [super description] stringByAppendingFormat:@" { underlying: 0x%08lX , distance: %lf , cost: %lf , endpoints: %@ }",(unsigned long)info,self.distance,self.cost,endpoints ] ;
}

+ (NSSet*)	linkInfoSet:(Sim::LinkInfoSet*)set {
	NSMutableSet * output = [NSMutableSet setWithCapacity:set->links().size()] ;
	
	std::vector<LinkInfo*>::const_iterator	here	=	set->links().begin() ;
	std::vector<LinkInfo*>::const_iterator	end		=	set->links().end() ;
	while ( here < end )
		{
		id it = [ [self alloc] initWithLinkInfo:*(here++) ] ;
		[output addObject:it] ;
		}
	
	return output ;
}


- (void)	replaceEndpointObjects:(NSSet*)allNodes {
	NSMutableSet * replacement = [NSMutableSet setWithCapacity:endpoints.count] ;
	
	for ( OCNodeInfo * node in endpoints )
		{
		id newNodes = [allNodes objectsPassingTest:^BOOL(id obj,BOOL*s){
			if ( [obj isEqual:node] )
				{
				*s = YES ;
				return YES ;
				}
			return NO ;
		}] ;
		
		id newNode = [newNodes anyObject] ;
		if ( newNode == 0 )
			[NSException raise:NSInternalInconsistencyException format:@"Didn't find suitable replacement"] ;
		
		[replacement addObject:newNode] ;
		}
	
	endpoints = replacement ;
}

@end
